目前的網站上只有 Articles(文章)作為發文類型,但既然要建置的是 Digital Garden,我也希望讓發文類型能擴及Notes、Literatures 與 MoC 這幾種類別,我是這樣定義他們的:
事實上這些發文類型在頁面和元件的程式碼幾乎是一致的,不同的地方只有在做查詢檔案的路徑不同。我預計他們存放的路徑會是
- @
- components
- ListPage.vue
- PostPage.vue
- content
- articles
- [...slug].vue
- index.vue
- notes
- [...slug].vue
- index.vue
- literatures
- [...slug].vue
- index.vue
- moc
- [...slug].vue
- index.vue
- pages
- ....
我只要把原本 @/articles/index.vue
的檔案內容除了查詢方法外抽出成 @components/ListPage.vue
,並把 @/articles/[...slug].vue
抽成 @components/PostPage.vue
,並且讓其他頁面的 index.vue
和 [...slug].vue
分別引用,就完成了。
各發文類型的 @/pages/post-type/index.vue
<template>
<ContentDoc v-slot="{ doc }">
<PostPage :post="(doc as Post)" />
</ContentDoc>
</template>
<script setup lang="ts">
import { Post } from '@/types/index'
</script>
與之相關的 @components/PostPage.vue
<template>
<article class="pb-4">
<PostHeader :post="post"/>
<PostContent :post="post"/>
<PostFooter :post="post"/>
</article>
</template>
<script setup lang="ts">
import { Post } from '@/types/index'
defineProps<{
post: Post
}>()
</script>
各發文類型的 @/pages/post-type/[...slug].vue
<template>
<ListPage />
</template>
與之相關的 @components/ListPage.vue
<template>
<section class="pb-24">
<div class="divide-y divide-gray-200">
<header class="pb-8 space-y-2 md:space-y-5">
<div>
<h1 class="tracking-tight font-extrabold text-gray-900 text-2xl leading-6 mb-1">
{{ slug.toUpperCase }}
</h1>
</div>
<SearchBar v-model="searchValue" placeholder-text="Search announce" />
</header>
<main>
<ul>
<li v-for="article in filteredArticles" :key="article._path" class="py-4">
<ListItem :item="article" />
</li>
</ul>
</main>
</div>
</section>
</template>
<script lang="ts" setup>
import { Post } from '@/types/index'
import { DateTime } from 'luxon';
const route = useRoute()
const slug = route.fullPath
const posts = [] // 各發文類型的查詢函式
const searchValue = ref('')
const { data } = await useAsyncData(slug, () =>
queryContent(slug)
.where({ slug: { $ne: slug }, _file: { $not: { $contains: 'index' } } })
.sort({ created_at: -1, published_at: -1 })
.find()
)
const post = data.value as Post[]
const articles = post.map((post) => {
const hasPostTags = !!post.tags
if (!hasPostTags) {
post.tags = []
}
return post
})
const filteredArticles = computed(() => {
return articles.filter((post: Post) => {
const tags = post.tags.filter((tag) => !!tag)
const searchContent =
post.title +
tags.map((tag: string) => (tag ? tag.split(' ').join('-') : '')) +
DateTime.fromISO(post.published_at).toFormat('yyyy-LL-dd')
return searchContent.toLowerCase().includes(searchValue.value.toLowerCase())
})
})
</script>
最後再去修改 @/compoents/TheHeader.vue
中的導覽列連結,加入這些新發文類型清單的連結,就算大功告成啦!